//
//  WBNetworkManager.swift
//  仿写微博
//
//  Created by tuimao on 17/7/13.
//  Copyright © 2017年 tuimao. All rights reserved.
//

import UIKit
import AFNetworking

enum WBHttpMethod {
    case GET
    case POST
}

class WBNetworkManager: AFHTTPSessionManager {
    //创建一个单例对象,静态/常量/闭包
    static let shared:WBNetworkManager = {
        
        let instance = WBNetworkManager()
        
        instance.responseSerializer.acceptableContentTypes?.insert("text/plain")
        
        return instance
    }()
    //用户账号类
    lazy var useAccount = WBUserAccount()
    
    var userlogon:Bool{
        return useAccount.access_token != nil
    }
    
    //MARK:  带token的网络请求（以后可以改为带cookie的），token是登录之后全称网络请求需要参数
    func tokenRequest(method:WBHttpMethod = .GET, URLString:String,parameters:[String:AnyObject]?,name: String? = nil, data: Data? = nil,completion:@escaping (_ json:AnyObject?,_ issuccess:Bool)->()) {
        //判断token是否有值，如果为nil那么重新登录获取token
        guard useAccount.access_token != nil else {
            //发送登录通知
            NotificationCenter.default.post(name: NSNotification.Name(rawValue: WBUserShouldLoginNotification), object: nil)
            print("用户没有登录，重新登录")
            completion(nil, false)
            return
        }
        //判断传参情况，如果没有给参数，那么我们只要把token的参数传过去就可以了
        var parameters = parameters
        if parameters == nil{
            parameters = [String:AnyObject]()
        }
        parameters!["access_token"] = useAccount.access_token as AnyObject?
        
        // 3> 判断 name 和 data
        if let name = name, let data = data {
            // 上传文件
            upload(URLString: URLString, parameters: parameters, name: name, data: data, completion: completion)
        } else {
            
            required(method: method, URLString: URLString, parameters: parameters, completion: completion)
        }
        
        //发送Get/POST请求
        required(method: method, URLString: URLString, parameters: parameters, completion: completion)
    }
    
    // MARK: - 封装 AFN 方法
    /// 上传文件必须是 POST 方法，GET 只能获取数据
    /// 封装 AFN 的上传文件方法
    ///
    /// - parameter URLString:  URLString
    /// - parameter parameters: 参数字典
    /// - parameter name:       接收上传数据的服务器字段(name - 要咨询公司的后台) `pic`
    /// - parameter data:       要上传的二进制数据
    /// - parameter completion: 完成回调
    func upload(URLString: String, parameters: [String: AnyObject]?, name: String, data: Data, completion: @escaping (_ json: AnyObject?, _ isSuccess: Bool)->()) {
        
        // 创建 formData
        /**
         1. data: 要上传的二进制数据
         2. name: 服务器接收数据的字段名
         3. fileName: 保存在服务器的文件名，大多数服务器，现在可以乱写
         很多服务器，上传图片完成后，会生成缩略图，中图，大图...
         4. mimeType: 告诉服务器上传文件的类型，如果不想告诉，可以使用 application/octet-stream
         image/png image/jpg image/gif
         */
        
        post(URLString, parameters: parameters, constructingBodyWith: { (formData) in
            //上传到服务器的data格式
            formData.appendPart(withFileData: data, name: name, fileName: "xxx", mimeType: "application/octet-stream")

        }, progress: { (_) in//进程监控
            
        }, success: { (task, json) in //成功回调
            completion(json as AnyObject, true)
            
        }) { (task, error) in //失败回调
            if (task?.response as? HTTPURLResponse)?.statusCode == 403 {
                print("Token 过期了")
                
                // 发送通知，提示用户再次登录(本方法不知道被谁调用，谁接收到通知，谁处理！)
                NotificationCenter.default.post(
                    name: NSNotification.Name(rawValue: WBUserShouldLoginNotification),
                    object: "bad token")
            }
            print("网络请求错误 \(error)")
            
            completion( nil, false)
            
        }
    }
    
    /// 封装AFN 的GET 和 POST请求
    ///
    /// - Parameters:
    ///   - method: GET/POST
    ///   - URLString: URLString
    ///   - parameters: 参数字典
    ///   - completion: 完成回调数据
    func required(method:WBHttpMethod = .GET, URLString:String,parameters:[String:AnyObject]?,completion:@escaping (_ json:AnyObject?,_ issuccess:Bool)->()){
        
        let success = {(task:URLSessionDataTask,json:Any?)->() in
            
            completion(json as AnyObject?, true)
        }
       
        let failure = {(task:URLSessionDataTask?,error:Error)->() in
            
         ////MARK:针对token过期的处理，提示用户登录 有可能死403或者别的
            if (task?.response as? HTTPURLResponse)?.statusCode  == 403 {
                //发送登录通知
                NotificationCenter.default.post(name: NSNotification.Name(rawValue: WBUserShouldLoginNotification), object: "badToken")
            }
            
            print("网络请求错误：\(error)")
            completion(nil, false)
        }
        
        if method == .GET{
            get(URLString, parameters: parameters, progress: nil, success: success, failure: failure)
        }else{
            post(URLString, parameters: parameters, progress: nil, success: success, failure: failure)
        }
        
    }
    
}
